
import heapq
import queue
import random
from .const_args import NodeType

class Analyzer():

    def __init__(self):
        self.priority_queue =[]
        self.current_time = 0
        self.process_recorder={}
        self.pid = 0
    
    def init_parameters(self,id):
        self.current_time = 0
        self.pid = id

    def init_queue(self,model):

        for node in model.all_nodes:
            if node.node_type == NodeType.element  and node.status=='on':
                duration = node.get_failure_time()
                if duration <=0:
                    duration = random.uniform(0, model.cp_time)

                if self.current_time+duration < model.cp_time:
                    failure_events=queue.Queue()
                    failure_events.put(node)
                    heapq.heappush(self.priority_queue,(self.current_time+duration,('down',failure_events)))

    def analyze(self,model):

        self.init_queue(model)

        while len(self.priority_queue) != 0:
            oc_time,event = heapq.heappop(self.priority_queue)
            if oc_time < model.cp_time:
                self.current_time = oc_time
                self.handle_event(event)
            else:
                self.process_queue()

        for node in model.all_nodes:
            if node.status != "down":
                if node.name not in self.process_recorder:
                    self.process_recorder[node.name]=[[('on',model.cp_time)]]
                else:
                    if len(self.process_recorder[node.name]) < self.pid+1:
                        self.process_recorder[node.name].append([('on',model.cp_time)])
            else:
                if node.name not in self.process_recorder:
                    self.process_recorder[node.name]=[[('down',model.cp_time)]]
                else:
                    if len(self.process_recorder[node.name]) < self.pid+1:
                        self.process_recorder[node.name].append([('down',model.cp_time)])



    def process_queue(self):
         pass

    def handle_event(self,event):
        status,nodes_queue = event

        while nodes_queue.qsize()!=0:
            node = nodes_queue.get()
            if status=='on':
                node.status='on'
                duration = node.get_failure_time()
                failure_events=queue.Queue()
                failure_events.put(node) 
                heapq.heappush(self.priority_queue,(self.current_time+duration,('down',failure_events)))
                if node.name in self.process_recorder:
                    self.process_recorder[node.name].append(('on',self.current_time+duration))
                else:
                    self.process_recorder[node.name]=[('on',self.current_time+duration)]
                node.propagate_success_status(nodes_queue)
            elif status=='down':
                node.status='down'
                if node.name not in self.process_recorder:
                    self.process_recorder[node.name] = [[('on',self.current_time)]]
                else:
                    if len(self.process_recorder[node.name]) < self.pid+1:
                        self.process_recorder[node.name].append([('on',self.current_time)])
                    else:
                        self.process_recorder[node.name][self.pid].append(('on',self.current_time))
                # 生成修复事件
                if node.repair_dist is not None:
                    duration = node.get_repair_time()
                    repair_events=queue.Queue()
                    repair_events.put(node)    
                    heapq.heappush(self.priority_queue,(self.current_time+duration,('on',repair_events)))

                node.propagate_failure_status(nodes_queue)

